package com.zhijian.wharf.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import com.zhijian.BusinessException;
import com.zhijian.autoconfigure.cache.CacheClient;
import com.zhijian.response.enums.ResponseCodeEnum;
import com.zhijian.util.AssertUtil;
import com.zhijian.util.EncryptUtil;
import com.zhijian.util.JsonUtil;
import com.zhijian.util.token.TokenBean;
import com.zhijian.util.token.TokenUtil;
import com.zhijian.wharf.config.Constants;
import com.zhijian.wharf.entity.dto.UserDto;
import com.zhijian.wharf.entity.po.User;
import com.zhijian.wharf.entity.vo.request.WebLoginVo;
import com.zhijian.wharf.entity.vo.response.AuthVo;
import com.zhijian.wharf.entity.vo.response.MenuVo;
import com.zhijian.wharf.enums.SystemEnum;
import com.zhijian.wharf.enums.UserStatusEnum;
import com.zhijian.wharf.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.List;

/**
 * @author HCG
 * @version 1.0
 * @date 2022/1/17
 */
@Service
@Slf4j
public class WebLoginServiceImpl extends LoginAbstract {

    @Autowired
    private UserService userService;

    @Autowired
    private CacheClient cacheClient;

    @Autowired
    private MenuService menuService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private UserGroupService userGroupService;

    @Autowired
    private TokenService tokenService;

    @Override
    public AuthVo login(Serializable serializable) {
        WebLoginVo vo = (WebLoginVo) serializable;
        if (!vo.getNoCaptcha()) {
            //验证码验证
            String verifyKey = Constants.Redis.CAPTCHA_CODE_KEY + vo.getUuid();
            String captcha = cacheClient.get(verifyKey);
            AssertUtil.notNull(captcha, "验证码不能为空");
            AssertUtil.check(!vo.getCode().equalsIgnoreCase(captcha), "验证码错误");
        }
        User user = userService.selectByPhoneAndPassword(vo.getPhone(), null);
        if (null == user) {
            throw new BusinessException(ResponseCodeEnum.FAILURE.code, "用户不存在");
        }
        //给前台传过来的密码加盐，然后加密
        String password = EncryptUtil.password(vo.getPassword(), user.getSalt());
        if (!password.equals(user.getPassword())) {
            throw new BusinessException(ResponseCodeEnum.FAILURE.code, "登录手机号或密码不正确");
        }
        if (user.getStatus().intValue() == UserStatusEnum.CANCEL.getCode()) {
            throw new BusinessException(ResponseCodeEnum.FAILURE.code, "此用户已停用，无法登陆");
        }
        //角色id数组
        List<Long> roleIds = userRoleService.selectRoleIdListByUserId(user.getId());
        //部门id数组
        List<Long> groupIds = userGroupService.selectGroupIdsByUserId(user.getId());
        UserDto personDto = UserDto.mergeFromPo(user);
        assert personDto != null;
        personDto.setSort(RandomUtil.randomInt(99999));
        personDto.setRoleIds(roleIds);
        //目前肯定是一个部门，所以取第一个就可
        personDto.setGroupId(CollectionUtil.isNotEmpty(groupIds) ? groupIds.get(0) : null);
        //搜一下此角色配置的菜单列表
        List<MenuVo> menuVos = menuService.renderTreeListByPersonId(user.getId());
        //生成新的token(账号、密码、生成密钥、过期时间、登陆时间)
        TokenBean tokenBean = new TokenBean(Constants.TOKEN_ACCESS_KEY, Constants.TOKEN_SECRET_KEY,
                "1.0", "login", "POST", null, JsonUtil.toString(personDto));
        String token = TokenUtil.generateToken(tokenBean, 0);
        cacheClient.setExSeconds(String.format(SystemEnum.WEB.getLoginTokenKey(), user.getPhone(), personDto.getSort()), token, SystemEnum.WEB.getLoginExpireTime());
        //缓存生成token的用户信息
        cacheClient.setExSeconds(String.format(SystemEnum.WEB.getUserKey(), token), JsonUtil.toString(personDto), SystemEnum.WEB.getLoginExpireTime());

        return AuthVo.builder()
                .token(token)
                .menuVos(menuVos)
                .user(AuthVo.UserVo.builder()
                        .id(user.getId())
                        .name(user.getName())
                        .phone(user.getPhone())
                        .userName(user.getUserName())
                        .roleIds(roleIds)
                        .groupIds(groupIds)
                        .build())
                .build();
    }

    @Override
    public boolean logout(String token) {
        UserDto userDto = tokenService.getUserDtoByToken(SystemEnum.WEB, token);
        if (userDto == null) {
            return false;
        }
        //清空token缓存
        cacheClient.del(String.format(SystemEnum.WEB.getLoginTokenKey(), userDto.getPhone(), userDto.getSort()));
        //清空token对应用户信息
        cacheClient.del(String.format(SystemEnum.WEB.getUserKey(), token));
        return true;
    }


}
